SoftmaxCrossEntropyWithLogits ================================= 计算 Softmax 交叉熵损失及梯度。 该算子首先对输入 ``logits`` 进行 Softmax 归一化得到概率,然后计算其与 ``labels`` 的交叉熵损失。如果启用了 ``need_grads``,则会计算损失相对于 ``logits`` 的梯度。 算法逻辑如下: 1. **Softmax**: .. math:: p_{i,j} = \frac{e^{x_{i,j}}}{\sum_{k} e^{x_{i,k}}} 2. **Cross Entropy Loss**: .. math:: loss_i = - \sum_{j} y_{i,j} \log(p_{i,j}) 3. **Gradients** (当 need_grads=1 时): .. math:: \frac{\partial loss}{\partial x_{i,j}} = p_{i,j} - y_{i,j} 输入: - **logits** - 输入数据地址(未归一化的对数概率)。形状为 :math:`[batch\_size, num\_of\_classes]`。 - **labels** - 标签数据地址。形状为 :math:`[batch\_size, num\_of\_classes]`。 - **probs** - 输出概率地址(Softmax 结果)。 - **grads** - 输出梯度地址。如果 ``need_grads`` 为 0,可忽略。 - **output** - 输出损失值地址(通常为标量或每个样本的损失)。 - **sum_data** - 中间计算缓冲区(Workspace),用于存储行和等临时数据。 - **batch_size** - 批大小。 - **num_of_classes** - 类别数量。 - **need_grads** - 是否需要计算梯度 (0: 不计算, 1: 计算)。 - **core_mask** - 核掩码(仅适用于共享存储版本)。 输出: - **probs** - 更新后的概率分布。 - **grads** - 计算得到的梯度(如启用)。 - **output** - 计算得到的交叉熵损失。 支持平台: ``FT78NE`` ``MT7004`` .. note:: - **FT78NE** 支持 Fp32 和 Int8 数据类型。 - **MT7004** 支持 Fp32 和 FP16 数据类型。 - 输入数据必须是二维矩阵,行优先存储。 - Int8 版本通常采用混合精度计算:输入/标签为 ``int8_t``,但输出(概率、梯度、损失)为 ``float`` 以保证精度。 **共享存储版本:** .. c:function:: void fp_softmax_cross_entropy_with_logits_s(float* logits, float* labels, float* probs, float* grads, float* output, float* sum_data, int batch_size, int num_of_classes, int need_grads, int core_mask) .. c:function:: void hp_softmax_cross_entropy_with_logits_s(float16* logits, float16* labels, float16* probs, float16* grads, float16* output, float16* sum_data, int batch_size, int num_of_classes, int need_grads, int core_mask) .. c:function:: void i8_softmax_cross_entropy_with_logits_s(int8_t* logits, int8_t* labels, float* probs, float* grads, float* output, float* sum_data, int batch_size, int num_of_classes, int need_grads, int core_mask) **C调用示例(FT78NE - Int8):** .. code-block:: c :linenos: :emphasize-lines: 19-21 #include #include int main(int argc, char* argv[]) { // 假设所有数据均位于DDR空间 int8_t* logits = (int8_t*)0xC0000000; int8_t* labels = (int8_t*)0xC1000000; float* probs = (float*)0xC2000000; float* grads = (float*)0xC3000000; float* output = (float*)0xC4000000; float* sum_data= (float*)0xC5000000; // Workspace int batch_size = 128; int num_of_classes = 1000; int need_grads = 1; int core_mask = 0xff; // 使用所有核心 // i8版本:输入为int8,输出及中间计算为float i8_softmax_cross_entropy_with_logits_s(logits, labels, probs, grads, output, sum_data, batch_size, num_of_classes, need_grads, core_mask); return 0; } **私有存储版本:** .. c:function:: void fp_softmax_cross_entropy_with_logits_p(float* logits, float* labels, float* probs, float* grads, float* output, float* sum_data, int batch_size, int num_of_classes, int need_grads) .. c:function:: void hp_softmax_cross_entropy_with_logits_p(float16* logits, float16* labels, float16* probs, float16* grads, float16* output, float16* sum_data, int batch_size, int num_of_classes, int need_grads) .. c:function:: void i8_softmax_cross_entropy_with_logits_p(int8_t* logits, int8_t* labels, float* probs, float* grads, float* output, float* sum_data, int batch_size, int num_of_classes, int need_grads) **C调用示例(MT7004 - FP16):** .. code-block:: c :linenos: :emphasize-lines: 16-18 #include int main(int argc, char* argv[]) { // 假设所有数据均位于AM空间 float16* logits = (float16*)0x10010000; float16* labels = (float16*)0x10020000; float16* probs = (float16*)0x10030000; float16* grads = (float16*)0x10040000; float16* output = (float16*)0x10050000; float16* sum_data=(float16*)0x10060000; int batch_size = 32; int num_of_classes = 512; int need_grads = 1; hp_softmax_cross_entropy_with_logits_p(logits, labels, probs, grads, output, sum_data, batch_size, num_of_classes, need_grads); return 0; }